# -*- coding=utf-8 -*-
from emmodels.em_rollback import Rollback
from emmodels.em_position2 import Assets
import pandas as pd
from LSTM.variableset import EMPath,EMVar
from sysdata import sys_base_data as sysBaseData
from emutils import time_utils, stk_utils, draw_utils, series_utils
import tushare as ts
import traceback
from emmobileapi import sys_strategy_fund as strategyFund
from dateutil.parser import parse
from datetime import timedelta
import os
from leanmodels.selffund_set import SelfFundSetModel
from emmongo import em_mongomanager as mongoManager

def get_wengu_zf30_stks():
    file_name = '30_4DAYPCT.csv'
    append_start = '2010-01-01'

    sh_his_datas = ts.get_k_data(code=EMVar.CODE_SH, index=True, start=append_start)
    date_series = pd.to_datetime(sh_his_datas[EMVar.date])
    sh_his_datas.set_index(date_series, inplace=True)

    destina_path = EMPath.data_file_full_path(is_common=True, fileName=file_name)
    if os.path.exists(destina_path):
        exit_df = pd.read_csv(destina_path, converters={EMVar.code:str}).sort_values('create_time')
        append_start = exit_df.iloc[-1]['create_time']
    else:
        exit_df = pd.DataFrame()


    date_series = sh_his_datas[EMVar.date]
    total_df = []
    append_date_series = sh_his_datas[append_start:][EMVar.date]
    for date in append_date_series:
        try:
            date_l, date_index_offset = stk_utils.em_get_date_offset(date, date_series, pre_offset=-3)
            add_date = date_l[-1]
            if not exit_df.empty and add_date in list(exit_df[EMVar.create_time]):
                print('%s 数据已经存在'% add_date)
                continue
            begin_date = parse(date_l[0]).strftime('%Y年%m月%d日')
            end_date =  parse(date_l[-1]).strftime('%Y年%m月%d日')
            ipo_date = (parse(date_l[0]) - timedelta(days=365)).strftime('%Y年%m月%d日')
            key = '%s收盘价比%s收盘价高30%%，上市小于%s'%(end_date,begin_date,ipo_date)
            df, total_count = strategyFund.req_strategy_fund(key=key, max_count=5, sleep=1)
            if not df.empty:
                df['create_time'] = add_date
                total_df.append(df)
            else:
                print('%s 无数据: %s' % (date, key))
        except Exception as e:
            print('%s 异常'% date)
            traceback.print_tb(e.__traceback__)
    if total_df:
        pend_datas = pd.concat(total_df, ignore_index=True)
    else:
        pend_datas = pd.DataFrame()
    sum_datas = pd.concat([exit_df, pend_datas]).sort_values('create_time')
    sum_datas = sum_datas[[EMVar.code, EMVar.stock_name, 'tag', EMVar.create_time]]
    sum_datas.to_csv(path_or_buf=EMPath.data_file_full_path(is_common=True, fileName=file_name))

    for index, item in sum_datas.iterrows():
        create_time = item['create_time']
        setModel = SelfFundSetModel(stkNo=item['code'], stkName=item['stockName'], price=0, predictBaseAccToClose=0, createDate=parse(create_time), strategy_name='4天涨幅超过30%')
        setModel.save_to_mongo()



class Rollback2(Rollback):


    def load_stks(self):
        self.total_datas = pd.read_csv(filepath_or_buffer=EMPath.data_file_full_path(is_common=True, fileName='30_4DAYPCT.csv'),converters={EMVar.code:str})
        self.total_datas[EMVar.create_time] = pd.to_datetime(self.total_datas[EMVar.create_time], errors='coerce')
        self.total_datas[EMVar.code] = self.total_datas[EMVar.code].astype(str)
        self.total_datas = self.total_datas.set_index([EMVar.create_time], drop=False)
        if not params:
            raise Exception('参数为空')

    def before_open(self, date):
        # 当前时间， 以及pre_offset天前加入的 STK 数据，默认5天
        self.registe_stks = self.__load_strategy_stks(date)
        self.registe_stks = self.registe_stks + self.assets.get_all_own_stocks()

    def __load_strategy_stks(self, date):
        # 当前时间， 以及pre_offset天前加入的 STK 数据，默认5天
        pre_offset = self.params['pre_offset'] if 'pre_offset' in self.params.keys() else 5
        date_l, date_index_offset = stk_utils.em_get_date_offset(date, self.date_series, pre_offset=-pre_offset, later_offset=15, ignore_later_offset=True)
        if date_l:
            # 绘制结果的开始日期和结束日期
            self.draw_begin_date = date_l[0]
            self.draw_end_date = date_l[-1]
            stks = self.util_load_strategy_stks(begin_date=date_l[0], end_date=date)
            return stks
        return []

    def after_close(self, date):
        pass

    def deliever(self, date_time, bar_datas):
        print('%s 进行到 %s'%(self.assets.strategy_name, date_time))

        bar_datas = bar_datas.fillna(0.1)

        ma = self.params['ma'] or 20
        stop_loss = self.params['stop_loss'] or -0.10
        stop_win = self.params['stop_win'] or 0.1
        is_reback = self.params['is_reback'] or True
        high_profit_reback = self.params['high_profit_reback'] or 0.05
        max_reback = self.params['max_reback'] or 0.02
        max_keep_days = self.params['max_keep_days'] or 5
        DIS_OPEN = self.params['DIS_OPEN'] or 0.02

        def handle_buy_stk(bar_low_price,bar_open_price ,bar_ma_price, tag):
            dis_open_price = (bar_open_price - bar_ma_price) / bar_ma_price
            dis_low_price = (bar_low_price - bar_ma_price) / bar_ma_price
            try:

                if dis_open_price < DIS_OPEN:
                    print('%s %s 均线:%3.2f, 开盘价:%3.2f, 开盘价比均线小于 %3.2f%%' % (sfund.code_with_name(), date_time, bar_ma_price, bar_open_price, DIS_OPEN*100))
                    return
                if (dis_low_price < 0.005 and dis_low_price > 0):
                    if self.assets.could_buy(date_time, code, bar_low_price):
                        print('均线:%3.2f, 最低价:%3.2f, %s' % (bar_ma_price, bar_low_price,'高于均线0.5%%左右最低价买入'))
                        self.assets.buy_stk(date_time=date_time, stkcode=code, name=sfund.stkname,
                                            price=bar_ma_price*(1+0.005),
                                            buy_total_money=self.assets.rest_assets,
                                            reason='高于均线0.5%%左右最低价买入')
                if (dis_low_price < 0):
                    if self.assets.could_buy(date_time, code, bar_ma_price):
                        print('%s %s 均线:%3.2f, 最低价:%3.2f, %s' % (sfund.code_with_name(), date_time, bar_ma_price, bar_low_price, tag or ''))
                        self.assets.buy_stk(date_time=date_time, stkcode=code, name=sfund.stkname,
                                            price=bar_ma_price,
                                            buy_total_money=self.assets.rest_assets,
                                            reason=tag or '')
            except Exception as e:
                traceback.print_tb(e.__traceback__)
                print(e)


        try:
            for index, item in bar_datas.iterrows():
                # 将nan 设置为0

                item = dict(item)
                code = item[EMVar.code]

                bar_close_price = float(item[EMVar.close])
                bar_low_price = float(item[EMVar.low])
                bar_open_price = float(item[EMVar.open])
                bar_ma5 = float(item[EMVar.MA5])
                bar_ma10 = float(item[EMVar.MA10])
                bar_ma20 = float(item[EMVar.MA20])
                bar_ma30 = float(item[EMVar.MA30])
                sfund = sysBaseData.get_self_fund(code)
                if self.assets.couldsaile(date_time, code):
                    self.common_saile(self.assets,
                                      code,
                                      sfund.stkname,
                                      bar_close_price,
                                      date_time,
                                      stop_loss=stop_loss,
                                      stop_win=stop_win,
                                      is_reback=is_reback,
                                      max_reback=max_reback,
                                      max_keep_days=max_keep_days,
                                      high_profit_reback=high_profit_reback,
                                      callback=None)
                    # 因为是判断是判断收盘价，止损卖出之后无法对这个股票再进行操作
                    continue
                # if not self.assets.is_own_stock(code):
                if not self.assets.have_own_stock():
                    # 记得改策略名
                    if ma == 5:
                        handle_buy_stk(bar_low_price,bar_open_price, bar_ma5,  '低于5日均线，在均线买入')
                    elif ma == 10:
                        handle_buy_stk(bar_low_price,bar_open_price, bar_ma10, '低于10日均线，在均线买入')
                    elif ma == 20:
                        handle_buy_stk(bar_low_price,bar_open_price, bar_ma20, '低于20日均线，在均线买入')
                    elif ma == 30:
                        handle_buy_stk(bar_low_price,bar_open_price, bar_ma30, '低于30日均线，在均线买入')

        except Exception as e:
            traceback.print_tb(e.__traceback__)
            print(e)

    def handle_record(self, own_stk_record):
        r = 'P'
        if (own_stk_record.buy_price < own_stk_record.cur_price):
            r = 'S'
        elif (own_stk_record.buy_price > own_stk_record.cur_price):
            r = 'F'
        sfund = sysBaseData.get_self_fund(own_stk_record.stk_code)
        df = sfund.get_index(append_now=False)
        fileName = '%s_%s_%s_%s' % (r, sfund.code_with_name(), own_stk_record.first_buy_day, own_stk_record.cur_date)
        draw_utils.draw_day_k(df[self.draw_begin_date: self.draw_end_date], isShow=False,
                              save_path=EMPath.strateg_info_file_full_path(is_common=True, strategyName=self.assets.strategy_name, fileName=fileName),
                              buy_date=own_stk_record.first_buy_day,
                              sell_date=own_stk_record.cur_date)
        pass


# get_wengu_zf30_stks()

params = [
    # 初始化参数
{
    'ma': 20,
    'stop_loss': -0.10,
    'stop_win': 0.1,
    'is_reback': True,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 5,
    'DIS_OPEN': 0.02
},
#     下面是修改止损点位
{
    'ma': 20,
    'stop_loss': -0.05,
    'stop_win': 0.1,
    'is_reback': True,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 5,
    'DIS_OPEN': 0.02
},
#     下面是修改是否回撤卖出
{
    'ma': 20,
    'stop_loss': -0.10,
    'stop_win': 0.1,
    'is_reback': False,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 5,
    'DIS_OPEN': 0.02
},
#     下面是修改持仓时间
{
    'ma': 20,
    'stop_loss': -0.10,
    'stop_win': 0.1,
    'is_reback': True,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 3,
    'DIS_OPEN': 0.02
},
{
    'ma': 20,
    'stop_loss': -0.10,
    'stop_win': 0.1,
    'is_reback': True,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 8,
    'DIS_OPEN': 0.02
},

{
    'ma': 20,
    'stop_loss': -0.10,
    'stop_win': 0.1,
    'is_reback': True,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 10,
    'DIS_OPEN': 0.02
},
{
    'ma': 20,
    'stop_loss': -0.10,
    'stop_win': 0.1,
    'is_reback': True,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 12,
    'DIS_OPEN': 0.02
},
# 下面是修改均线
{
    'ma': 10,
    'stop_loss': -0.10,
    'stop_win': 0.1,
    'is_reback': True,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 3,
    'DIS_OPEN': 0.02
},
{
    'ma': 5,
    'stop_loss': -0.10,
    'stop_win': 0.1,
    'is_reback': True,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 3,
    'DIS_OPEN': 0.02
},
{
    'ma': 30,
    'stop_loss': -0.10,
    'stop_win': 0.1,
    'is_reback': True,
    'high_profit_reback': 0.05,
    'max_reback': 0.02,
    'max_keep_days': 3,
    'DIS_OPEN': 0.02
}

]

# params = [
# {'pre_offset':5,'stop_loss': -0.1, 'high_profit_reback': 0.05, 'max_keep_days': 3, 'max_reback': 0.02, 'is_reback': True, 'ma': 5, 'stop_win': 0.1, 'DIS_OPEN': 0.02}
# ]
for pre_offset in [5, 10, 15]:
    for item in params:
        item['pre_offset'] = pre_offset
        print(item)
        strategy_name = 'TOP_30_5DAY_MA%s_T%s' % (item['ma'], EMVar.format_now(EMVar.FORMATE_YMD_HMS))
        strategy_detail = str(item)
        rollback = Rollback2(mode=Rollback2.MODE_DAY, is_real=False, start_date='2016-01-01',end_date='2017-01-01', params=item, strategy_name='4天涨幅超过30%',assets_name=strategy_name, assets_detail=strategy_detail)
        # rollback.load_stks()
        rollback.begin()
        # rollback.begin_real(date='2017-10-25')



